package com.ys.dubbo.cloud.redis.version.gateway.v2.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.ys.dubbo.cloud.redis.version.gateway.v2.bean.RouteConfInfo;
import com.ys.dubbo.cloud.redis.version.gateway.v2.bean.RouteDefinitionVo;
import com.ys.dubbo.cloud.redis.version.gateway.v2.repository.RouteConfMapper;
import com.ys.dubbo.cloud.redis.version.gateway.v2.service.RouteConfService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>@description:</p>
 *
 * @author yangshuang
 * @version 1.0
 * @date 2019/7/16 11:23
 */
@Slf4j
@Service
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class RouteConfServiceImpl implements RouteConfService {


    private final ApplicationEventPublisher applicationEventPublisher;


    private final RedisTemplate redisTemplate;

    private final RouteConfMapper routeConfMapper;

    private static final String ROUTE_KEY = "";

    @Override
    public List<RouteConfInfo> routes() {

        //查询条件
        return routeConfMapper.selectList();
    }

    @Override
    public Mono<Void> editRoutes(JSONArray routes) {
        //清空redis缓存
        Boolean result = redisTemplate.delete(ROUTE_KEY);
        log.info("清空网关路由 {} ", result);

        List<RouteDefinitionVo> routeDefinitionVos = new ArrayList<>();

        routes.forEach(value -> {

            RouteDefinitionVo vo = new RouteDefinitionVo();
            Map<String, Object> map = (Map) value;

            Object id = map.get("routeId");
            if (id != null) {
                vo.setRouteId(String.valueOf(id));
            }

            Object predicates = map.get("predicates");
            if (predicates != null) {
                JSONArray predicatesArray = (JSONArray) predicates;
                List<PredicateDefinition> predicateDefinitionList =
                        predicatesArray.toJavaList(PredicateDefinition.class);
                vo.setPredicates(predicateDefinitionList);
            }

            Object filters = map.get("filters");
            if (filters != null) {
                JSONArray filtersArray = (JSONArray) filters;
                List<FilterDefinition> filterDefinitionList
                        = filtersArray.toJavaList(FilterDefinition.class);
                vo.setFilters(filterDefinitionList);
            }

            Object uri = map.get("uri");
            if (uri != null) {
                vo.setUri(URI.create(String.valueOf(uri)));
            }
            Object order = map.get("order");
            if (order != null) {
                vo.setOrder(Integer.parseInt(String.valueOf(order)));
            }

            redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(RouteDefinitionVo.class));
            redisTemplate.opsForHash().put(ROUTE_KEY, vo.getRouteId(), vo);
            routeDefinitionVos.add(vo);
        });

        // 逻辑删除全部
//            RouteConfInfo condition = new RouteConfInfo();
//            condition.setDelFlag(CommonConstant.STATUS_NORMAL);
//            this.delete(new EntityWrapper<>(condition));
        //插入生效路由
        List<RouteConfInfo> routeConfList = routeDefinitionVos.stream().map(item -> {
            RouteConfInfo routeConf = new RouteConfInfo();
            routeConf.setRouteId(item.getRouteId());
            routeConf.setFilters(JSON.toJSONString(item.getFilters()));
            routeConf.setPredicates(JSON.toJSONString(item.getPredicates()));
            routeConf.setOrder(item.getOrder());
            routeConf.setUri(item.getUri().toString());
            return routeConf;
        }).collect(Collectors.toList());
        //批量更新
        //    this.insertBatch(routeConfList);
        log.debug("更新网关路由结束 ");

        this.applicationEventPublisher.publishEvent(new RefreshRoutesEvent(this));
        return Mono.empty();
    }
}
